package affd.logic;

import java.io.File;

import com.sun.star.beans.PropertyValue;
import com.sun.star.beans.XPropertySet;
import com.sun.star.bridge.XUnoUrlResolver;
import com.sun.star.comp.helper.Bootstrap;
import com.sun.star.frame.XComponentLoader;
import com.sun.star.frame.XStorable;
import com.sun.star.lang.XComponent;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.task.ErrorCodeIOException;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;
import com.sun.star.util.CloseVetoException;
import com.sun.star.util.XCancellable;
import com.sun.star.util.XCloseable;

public class ConverterClientDebug extends ConverterClient {
	
	public static final String FILTER_HTML = "HTML";
	public static final String FILTER_PDF = "pdf";
	
	private XComponentContext contex;
	private XComponentLoader loader;
	private String url;
	
	public ConverterClientDebug(int port) {
		super("localhost", Integer.toString(port));
		
		// Build URL
		url = "uno:socket,host=localhost,port=" + port +";urp;StarOffice.ServiceManager";		
	}
	
	protected void connect() throws LogicException {
		try {
		// Create remote connection using the interprocess connection mechanism
		contex = Bootstrap.createInitialComponentContext(null);
		XMultiComponentFactory tempFactory = contex.getServiceManager();
        Object urlResolver  = tempFactory.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", contex);
        XUnoUrlResolver xUnoUrlResolver = (XUnoUrlResolver) UnoRuntime.queryInterface(XUnoUrlResolver.class, urlResolver);
            
        // Connect
        Object initialObject = xUnoUrlResolver.resolve(url);
        XPropertySet xPropertySet = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class,initialObject);
        contex = (XComponentContext) UnoRuntime.queryInterface(XComponentContext.class, xPropertySet.getPropertyValue("DefaultContext"));
		
		//Get component loader
        XMultiComponentFactory factory = contex.getServiceManager();
		Object desktop = factory.createInstanceWithContext("com.sun.star.frame.Desktop", contex);
		loader = (XComponentLoader) UnoRuntime.queryInterface(XComponentLoader.class, desktop);
		} catch (Exception e) {
			throw new LogicException("Failed to connect " + url + " !", e);
		}
	}
	
	public String convert(String filename, String outputExtension) throws LogicException{
		if(getExtension(filename).equalsIgnoreCase(outputExtension)) {
			return filename;
		}
		
		// Set filter type
		String filter = "";
		if(outputExtension.equals(EXTENSION_HTML)) {
			filter = FILTER_HTML;
		}
		else if(outputExtension.equals(EXTENSION_PDF)) {
			filter = FILTER_PDF;
		}
		else {
			throw new LogicException("Unsupported output extension " + outputExtension+ " !");
		}
		
		Object document = null;
		XStorable storable = null;
		
		// Connect to the OpenOffice service
		if(contex == null || loader == null) {
			try {
				connect();
			}
			catch(Exception e) {
				throw new LogicException("Failed to connect to " + url + " !", e);
			}
		}
		
		// Build file URLs
		File file = new File(filename);
		String fileAbsolute = file.getAbsolutePath().replace( '\\', '/' );
		
		// Remove file separator from absolute path
		if(fileAbsolute.startsWith(File.separator)) {
			fileAbsolute = fileAbsolute.substring(1);
		}
		
		String inputUrl = "file:///" + fileAbsolute;
		String outputUrl = setExtension(inputUrl, ConverterClient.EXTENSION_HTML);
		String ouputFilename = setExtension(filename, ConverterClient.EXTENSION_HTML);
		
		// Set open properties
		PropertyValue[] openProperties = new PropertyValue[1];
		openProperties[0] = new PropertyValue();
		openProperties[0].Name = "Hidden";
		openProperties[0].Value = new Boolean(false);
		
		// Set store properties
		PropertyValue storeProperties[] = new PropertyValue[2];
		storeProperties[0] = new PropertyValue();
		storeProperties[0].Name = "Overwrite";
		storeProperties[0].Value = new Boolean(true);
		storeProperties[1] = new PropertyValue();
		storeProperties[1].Name = "FilterName";
		storeProperties[1].Value = filter;
		
		try {
			// Open document
			document = loader.loadComponentFromURL(inputUrl, "_blank", 0, openProperties);
		
			// Store document
			storable = (XStorable) UnoRuntime.queryInterface(XStorable.class, document);
			storable.storeToURL(outputUrl, storeProperties);
		}
		catch(Exception e) {
			// Cancel the store process if possible
			XCancellable cancel = (XCancellable) UnoRuntime.queryInterface(XCancellable.class, storable);
		    if (cancel != null) {
		    	cancel.cancel();
		    }
		    
		    String message = "Failed to convert document " + filename +" !";
		    
		    // Get error code
			if(e instanceof ErrorCodeIOException) {
				ErrorCodeIOException errorCode = (ErrorCodeIOException) e;
				message = message + " (Erro code: " + errorCode.ErrCode + ")";
			}
		    
			throw new LogicException(message, e);
		}
		finally
		{
			// Try close the store process
			XCloseable closeable = (XCloseable) UnoRuntime.queryInterface(XCloseable.class, storable);
			if (closeable != null) {
				try {
					closeable.close(false);
				}
				catch (CloseVetoException e) {
					// TODO Throw LogicException ?
				}
			}
			else {
				XComponent component = (XComponent) UnoRuntime.queryInterface(XComponent.class, storable);
				if(component != null) {
					component.dispose();
				}
			}
		}

		return ouputFilename;
	}

}
